package com.imis.module.online.table.bus;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.DataBaseConstant;
import com.imis.base.constant.enums.ArgumentResponseEnum;
import com.imis.base.globle.response.BaseResponse;
import com.imis.base.globle.response.CommonResponse;
import com.imis.base.util.ConvertUtils;
import com.imis.base.util.table.DataBaseTableProcess;
import com.imis.base.util.table.DataBaseTableUtil;
import com.imis.base.util.table.model.TableFormConfigModel;
import com.imis.base.util.table.model.TableTemplateConverter;
import com.imis.base.util.table.service.IDataBaseTableHandleService;
import com.imis.module.base.BaseBus;
import com.imis.module.online.table.model.converter.TableFieldsConverter;
import com.imis.module.online.table.model.converter.TableHeadConverter;
import com.imis.module.online.table.model.converter.TableIndexConverter;
import com.imis.module.online.table.model.po.TableFields;
import com.imis.module.online.table.model.po.TableHead;
import com.imis.module.online.table.model.po.TableIndex;
import com.imis.module.online.table.model.ro.*;
import com.imis.module.online.table.model.vo.TableBasicVO;
import com.imis.module.online.table.model.vo.TableHeadVO;
import com.imis.module.online.table.model.vo.TableVO;
import com.imis.module.online.table.service.ITableFieldsService;
import com.imis.module.online.table.service.ITableHeadService;
import com.imis.module.online.table.service.ITableIndexService;
import com.imis.module.system.model.converter.SysDataSourceConverter;
import com.imis.module.system.model.po.SysDataSource;
import com.imis.module.system.model.vo.SysDataSourceVO;
import com.imis.module.system.service.ISysDataSourceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * <p>
 * 在线开发-数据库表 业务处理类
 * </p>
 *
 * @author XinLau
 * @since 2020-10-03
 */
@Slf4j
@Service
public class DataBaseTableBus extends BaseBus {

    /**
     * 在线开发-数据库表表信息 服务类
     */
    private ITableHeadService serviceByTableHeadService;

    @Autowired
    public void setTableHeadService(ITableHeadService serviceByTableHeadService) {
        this.serviceByTableHeadService = serviceByTableHeadService;
    }

    /**
     * 在线开发-数据库表字段信息 服务类
     */
    private ITableFieldsService serviceByTableFieldsService;

    @Autowired
    public void setTableFieldsService(ITableFieldsService serviceByTableFieldsService) {
        this.serviceByTableFieldsService = serviceByTableFieldsService;
    }

    /**
     * 在线开发-数据库表索引 服务类
     */
    private ITableIndexService serviceByTableIndexService;

    @Autowired
    public void setTableIndexService(ITableIndexService serviceByTableIndexService) {
        this.serviceByTableIndexService = serviceByTableIndexService;
    }

    /**
     * 系统数据源管理 服务类
     */
    private ISysDataSourceService serviceByDataSourceService;

    @Autowired
    public void setDataSourceService(ISysDataSourceService serviceByDataSourceService) {
        this.serviceByDataSourceService = serviceByDataSourceService;
    }

    /**
     * 数据库表表信息新增验证
     *
     * @param tableHeadAdd - 数据库表表信息-新增
     * @return TableHead - 数据库表表信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private TableHead tableHeadAddVerification(final TableHeadAddDTO tableHeadAdd) {
        String tableName = tableHeadAdd.getTableName();
        TableHead tableHead = serviceByTableHeadService.getOne(Wrappers.<TableHead>lambdaQuery().eq(TableHead::getTableName, tableName), Boolean.FALSE);
        ArgumentResponseEnum.TABLE_HEAD_ADD_ERR_01.assertIsNull(tableHead, tableName);
        tableHead = TableHeadConverter.INSTANCE.getAddEntity(tableHeadAdd);
        return tableHead;
    }

    /**
     * 判断数据库表表信息是否改变
     *
     * @param tableHead       - 数据库表表信息
     * @param tableHeadUpdate - 数据库表表信息-更新
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private Boolean dataBaseTableIsChange(final TableHead tableHead, final TableHeadUpdateDTO tableHeadUpdate) {
        // 数据库表的表名、数据库表的表注释
        if (!ConvertUtils.compareValue(tableHead.getTableName(), tableHeadUpdate.getTableName())
                || !ConvertUtils.compareValue(tableHead.getTableDescription(), tableHeadUpdate.getTableDescription())) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 数据库表表信息更新验证
     *
     * @param tableHeadUpdate - 数据库表表信息-更新
     * @return TableHead - 数据库表表信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private TableHead tableHeadUpdateVerification(final TableHeadUpdateDTO tableHeadUpdate) {
        Long tableHeadId = tableHeadUpdate.getId();
        TableHead tableHead = serviceByTableHeadService.getById(tableHeadId);
        ArgumentResponseEnum.TABLE_HEAD_UPDATE_ERR_01.assertNotNull(tableHead);
        if (this.dataBaseTableIsChange(tableHead, tableHeadUpdate)) {
            // isSynchronize 数据库表的表名与数据库表的表注释发生改变
            tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_N);
            Integer tableVersion = tableHead.getTableVersion();
            if (ConvertUtils.isEmpty(tableVersion)) {
                tableVersion = 1;
            }
            // tableVersion 自增
            tableHead.setTableVersion(++tableVersion);
        }
        TableHeadConverter.INSTANCE.getUpdateEntity(tableHead, tableHeadUpdate);
        return tableHead;
    }

    /**
     * 判断数据库表字段信息是否改变
     *
     * @param tableFields       - 数据库表字段信息
     * @param tableFieldsUpdate - 数据库表字段信息-更新
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private Boolean dataBaseTableFieldsIsChange(final TableFields tableFields, final TableFieldsUpdateDTO tableFieldsUpdate) {
        if (!ConvertUtils.compareValue(tableFields.getId(), tableFieldsUpdate.getId())
                || !ConvertUtils.compareValue(tableFields.getTableHeadId(), tableFieldsUpdate.getTableHeadId())
                || !ConvertUtils.compareValue(tableFields.getFieldName(), tableFieldsUpdate.getFieldName())
                || !ConvertUtils.compareValue(tableFields.getFieldTxt(), tableFieldsUpdate.getFieldTxt())
                || !ConvertUtils.compareValue(tableFields.getFieldLength(), tableFieldsUpdate.getFieldLength())
                || !ConvertUtils.compareValue(tableFields.getFieldPointLength(), tableFieldsUpdate.getFieldPointLength())
                || !ConvertUtils.compareValue(tableFields.getFieldType(), tableFieldsUpdate.getFieldType())
                || !ConvertUtils.compareValue(tableFields.getIsNull(), tableFieldsUpdate.getIsNull())
                || !ConvertUtils.compareValue(tableFields.getIsKey(), tableFieldsUpdate.getIsKey())
                || !ConvertUtils.compareValue(tableFields.getFieldDefaultValue(), tableFieldsUpdate.getFieldDefaultValue())) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 数据库表字段信息更新验证
     *
     * @param deleteFieldIds        - 数据库表字段信息-删除
     * @param tableFieldsUpdateList - 数据库表字段信息-更新
     * @param tableHead             - 数据库表表信息-更新
     * @return TableFieldsDTO - 数据库表字段信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private TableFieldsDTO tableFieldsUpdateVerification(final TableHead tableHead, final List<Long> deleteFieldIds, final List<TableFieldsUpdateDTO> tableFieldsUpdateList) {
        // 1.数据库表字段信息-删除验证
        if (deleteFieldIds.size() > 0) {
            List<TableFields> tableFieldsDeleteList = serviceByTableFieldsService.listByIds(deleteFieldIds);
            assertThat(tableFieldsDeleteList.size()).as("数据库表字段信息删除失败").isEqualTo(deleteFieldIds.size());
        }
        // 2.数据库表字段信息-更新验证
        List<TableFields> tableFieldsAddList = new ArrayList<>();
        Long tableHeadId = tableHead.getId();
        tableFieldsUpdateList.forEach(tableFieldsUpdate -> {
            Long tableFieldId = tableFieldsUpdate.getId();
            if (ConvertUtils.isEmpty(tableFieldId)) {
                // 数据库表字段信息-新增
                tableFieldsAddList.add(TableFieldsConverter.INSTANCE.getUpdateEntity(tableFieldsUpdate, tableHeadId));
                tableFieldsUpdateList.remove(tableFieldsUpdate);
                tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_N);
            } else {
                // 数据库表字段信息-修改
                TableFields tableFields = serviceByTableFieldsService.getById(tableFieldId);
                if (this.dataBaseTableFieldsIsChange(tableFields, tableFieldsUpdate)) {
                    tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_N);
                }
                assertThat(tableFieldId).as("数据库表字段信息更新失败-数据库表字段编号不一致").isEqualTo(tableFields.getId());
                assertThat(tableFieldsUpdate.getTableHeadId()).as("数据库表字段信息更新失败-数据库表编号不一致")
                        .isEqualTo(tableHeadId)
                        .isEqualTo(tableFields.getTableHeadId());
            }
        });
        return new TableFieldsDTO(tableHead, tableFieldsAddList, tableFieldsUpdateList);
    }

    /**
     * 判断数据库表索引信息是否改变
     *
     * @param tableIndex       - 数据库表索引信息
     * @param tableIndexUpdate - 数据库表索引信息-更新
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private Boolean dataBaseTableIndexIsChange(final TableIndex tableIndex, final TableIndexUpdateDTO tableIndexUpdate) {
        if (!ConvertUtils.compareValue(tableIndex.getId(), tableIndexUpdate.getId())
                || !ConvertUtils.compareValue(tableIndex.getTableHeadId(), tableIndexUpdate.getTableHeadId())
                || !ConvertUtils.compareValue(tableIndex.getIndexName(), tableIndexUpdate.getIndexName())
                || !ConvertUtils.compareValue(tableIndex.getIndexField(), tableIndexUpdate.getIndexField())
                || !ConvertUtils.compareValue(tableIndex.getIndexType(), tableIndexUpdate.getIndexType())) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 数据库表索引信息更新验证
     *
     * @param deleteIndexIds       - 数据库表索引信息-删除
     * @param tableIndexUpdateList - 数据库表索引信息-更新
     * @param tableHead            - 数据库表表信息-更新
     * @return TableFieldsDTO - 数据库表字段信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:42
     */
    private TableIndexDTO tableIndexUpdateVerification(final TableHead tableHead, final List<Long> deleteIndexIds, final List<TableIndexUpdateDTO> tableIndexUpdateList) {
        // 1.数据库表字段信息-删除验证
        List<TableIndex> tableIndexDeleteList = new ArrayList<>();
        if (deleteIndexIds.size() > 0) {
            tableIndexDeleteList = serviceByTableIndexService.listByIds(deleteIndexIds);
            assertThat(tableIndexDeleteList.size()).as("数据库表索引信息删除失败").isEqualTo(deleteIndexIds.size());
            tableIndexDeleteList.forEach(tableIndex -> tableIndex.setDelFlag(CommonConstant.DEL_FLAG_DELETE));
        }
        // 2.数据库表字段信息-更新验证
        Long tableHeadId = tableHead.getId();
        List<TableIndex> tableIndexAddList = new ArrayList<>();
        List<TableIndex> finalTableIndexDeleteList = tableIndexDeleteList;
        tableIndexUpdateList.forEach(tableIndexUpdate -> {
            Long tableIndexId = tableIndexUpdate.getId();
            if (ConvertUtils.isEmpty(tableIndexId)) {
                // 数据库表索引信息-新增
                tableIndexAddList.add(TableIndexConverter.INSTANCE.getUpdateEntity(tableIndexUpdate, tableHeadId));
                tableIndexUpdateList.remove(tableIndexUpdate);
                tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_N);
            } else {
                // 数据库表索引信息-更新
                TableIndex tableIndex = serviceByTableIndexService.getById(tableIndexId);
                if (this.dataBaseTableIndexIsChange(tableIndex, tableIndexUpdate)) {
                    tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_N);
                }
                assertThat(tableIndexId).as("数据库表索引信息更新失败-数据库表索引编号不一致").isEqualTo(tableIndex.getId());
                assertThat(tableIndexUpdate.getTableHeadId()).as("数据库表索引信息更新失败-数据库表编号不一致")
                        .isEqualTo(tableHeadId)
                        .isEqualTo(tableIndex.getTableHeadId());

                TableIndexConverter.INSTANCE.getUpdateEntity(tableIndex, tableIndexUpdate);
                finalTableIndexDeleteList.add(tableIndex);
            }
        });
        return new TableIndexDTO(tableHead, tableIndexAddList, finalTableIndexDeleteList);
    }

    /**
     * 进行正常同步
     *
     * @param tableHeadId - 数据库表编号
     * @param tableName   - 数据库表表名
     * @param model       - 数据库表的表单配置模型
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/5 15:20
     */
    private void doNormalSynchronization(final Long tableHeadId, final String tableName, final TableFormConfigModel model) throws SQLException, IOException {
        long startTime = System.currentTimeMillis();
        // 1.判断数据库表是否存在（T-存在；F不存在）
        Boolean isExist = DataBaseTableUtil.judgeTableIsExit(tableName);
        log.debug("判断表是否存在消耗时间" + (System.currentTimeMillis() - startTime) + "毫秒");
        if (isExist) {
            // 2.表字段变更处理
            DataBaseTableProcess process = new DataBaseTableProcess();
            List<String> list = process.updateTable(model);
            for (String sql : list) {
                if (ConvertUtils.isEmpty(sql) || ConvertUtils.isEmpty(sql.trim())) {
                    continue;
                }
                Boolean update = serviceByTableIndexService.executeDataDefinitionLanguage(sql);
                assertThat(Boolean.TRUE).as("表字段变更处理").isEqualTo(update).isTrue();
            }
            // 3.表索引变更处理
            // 表已存在 那么就先删除索引
            List<TableIndex> tableIndexList = serviceByTableIndexService.list(new LambdaQueryWrapper<TableIndex>().eq(TableIndex::getTableHeadId, tableHeadId));
            // 不能删除不存在的索引 ，删除前判断一下
            tableIndexList.forEach(tableIndex -> {
                if (CommonConstant.TO_UPPER_CASE_N.equals(tableIndex.getIsSynchronize()) || CommonConstant.DEL_FLAG_DELETE.equals(tableIndex.getDelFlag())) {
                    String countIndexSql = process.getCountIndexSql(tableIndex.getIndexName(), tableName);
                    if (serviceByTableIndexService.isExistIndex(countIndexSql)) {
                        String deleteIndexSql = process.dropIndexesSql(tableIndex.getIndexName(), tableName);
                        try {
                            log.info("删除索引 executeDataDefinitionLanguage:" + deleteIndexSql);
                            Boolean deleteIndex = serviceByTableIndexService.executeDataDefinitionLanguage(deleteIndexSql);
                            assertThat(Boolean.TRUE).as("删除索引").isEqualTo(deleteIndex).isTrue();
                            // 删除索引后，将逻辑删除数据，从物理表里删除
                            if (CommonConstant.DEL_FLAG_DELETE.equals(tableIndex.getDelFlag())) {
                                serviceByTableIndexService.removeById(tableIndex.getId());
                            }
                        } catch (Exception e) {
                            log.error("删除表【" + tableName + "】索引(" + tableIndex.getIndexName() + ")失败!", e);
                        }
                    } else {
                        // 3.2库中无索引，则将逻辑删除数据，从物理表里删除
                        if (CommonConstant.DEL_FLAG_DELETE.equals(tableIndex.getDelFlag())) {
                            serviceByTableIndexService.removeById(tableIndex.getId());
                        }
                    }
                }
            });
        } else {
            DataBaseTableProcess.createTable(model);
        }
    }

    /**
     * 进行强制同步
     *
     * @param tableName - 数据库表表名
     * @param model     - 数据库表的表单配置模型
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/5 15:20
     */
    private void doForceSynchronization(final String tableName, final TableFormConfigModel model) throws SQLException, IOException {
        IDataBaseTableHandleService handler = DataBaseTableUtil.getTableHandle();
        String sql = handler.dropTableSql(tableName);
        Boolean dropTable = serviceByTableIndexService.executeDataDefinitionLanguage(sql);
        assertThat(Boolean.TRUE).as("删除数据库表").isEqualTo(dropTable).isTrue();
        DataBaseTableProcess.createTable(model);
    }

    /**
     * 创建指定库表的库表索引
     *
     * @param tableHeadId - 数据库表编号
     * @param tableName   - 数据库表表名
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/5 15:20
     */
    private void createTableIndex(final Long tableHeadId, final String tableName) throws SQLException {
        // 1、获取指定库表的库表索引
        List<TableIndex> tableIndexList = serviceByTableIndexService.list(Wrappers.<TableIndex>lambdaQuery().eq(TableIndex::getTableHeadId, tableHeadId).eq(TableIndex::getDelFlag, CommonConstant.DEL_FLAG_NOT_DELETE).eq(TableIndex::getIsSynchronize, CommonConstant.TO_UPPER_CASE_N));
        IDataBaseTableHandleService handler = DataBaseTableUtil.getTableHandle();
        tableIndexList.forEach(tableIndex -> {
            String sql = handler.creatIndexes(tableIndex, tableName);
            Boolean creatIndexes = serviceByTableIndexService.executeDataDefinitionLanguage(sql);
            assertThat(Boolean.TRUE).as("创建数据库索引").isEqualTo(creatIndexes).isTrue();
            // 修改索引配置为已同步
            tableIndex.setIsSynchronize(CommonConstant.TO_UPPER_CASE_Y);
        });
        // 更新指定库表的库表索引信息
        if (tableIndexList.isEmpty()) {
            return;
        }
        serviceByTableIndexService.updateBatchById(tableIndexList);
    }

    /**
     * 移除数据库表校验
     *
     * @param tableIdentification - 数据库表主键
     * @return TableHead -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    private TableHead tableHeadRemoveVerification(final Long tableIdentification) {
        // 1、数据库表不存在
        assertThat(ConvertUtils.isNotEmpty(tableIdentification)).as("数据库表不存在").isTrue();
        TableHead tableHead = serviceByTableHeadService.getById(tableIdentification);
        assertThat(tableHead).as("数据库表不存在").isNotNull();
        // 2、数据库表存在（判断是否被关联，被关联不允许移除）
        List<TableFields> tableFieldList = serviceByTableFieldsService.list(new LambdaQueryWrapper<TableFields>().eq(TableFields::getMainTable, tableHead.getTableName()));
        assertThat(tableFieldList).as("数据库表被其他数据库表关联").isEmpty();
        return tableHead;
    }

    /**
     * 按表名称删除数据库表
     *
     * @param tableName - 数据库表表名称
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:44
     */
    private Boolean doDataBaseTableRemoveByTableName(final String tableName) {
        Boolean isExist = DataBaseTableUtil.judgeTableIsExit(tableName);
        if (isExist) {
            try {
                String dropTableSql = DataBaseTableUtil.getTableHandle().dropTableSql(tableName);
                log.info("执行 executeDataDefinitionLanguage： " + dropTableSql);
                Boolean dropTable = serviceByTableIndexService.executeDataDefinitionLanguage(dropTableSql);
                assertThat(Boolean.TRUE).as("删除数据库表").isEqualTo(dropTable).isTrue();
            } catch (SQLException throwable) {
                log.debug(throwable.getMessage(), throwable);
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 按数据库表主键删除数据库表相关
     *
     * @param tableIdentification - 数据库表主键
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:44
     */
    private Boolean doDataBaseTableDeleteByTableIdentification(final Long tableIdentification) {
        // 1、数据库表表信息
        boolean removeTableHeadById = serviceByTableHeadService.removeById(tableIdentification);
        assertThat(removeTableHeadById).as("数据库表表信息删除失败").isTrue();
        // 2、数据库表字段信息
        boolean removeTableFieldsByTableHeadId = serviceByTableFieldsService.remove(new LambdaQueryWrapper<TableFields>().eq(TableFields::getTableHeadId, tableIdentification));
        assertThat(removeTableFieldsByTableHeadId).as("数据库表字段删除失败").isTrue();
        // 3、数据库表索引信息
        Boolean removeTableIndexByTableHeadId = serviceByTableIndexService.remove(new LambdaQueryWrapper<TableIndex>().eq(TableIndex::getTableHeadId, tableIdentification));
        // TODO:This：所有有这个 @TableField("table_head_id") private Long tableHeadId 字段的可能都需要作删除处理
        assertThat(Boolean.TRUE).as("数据库表相关删除失败")
                .isEqualTo(removeTableHeadById)
                .isEqualTo(removeTableFieldsByTableHeadId);
        return Boolean.TRUE;
    }

    /**
     * 查询数据库表
     *
     * @param pagingQueryTableDTO - 数据库表查询对象
     * @return Result - TableBasicVO 数据库表表基础信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:07
     */
    public CommonResponse<Page<TableBasicVO>> pagingQueryTableListByParameter(final PagingQueryTableDTO pagingQueryTableDTO) {
        Page<TableBasicVO> tableListByParameter = serviceByTableHeadService.pagingQueryTableListByParameter(pagingQueryTableDTO);
        return new CommonResponse(tableListByParameter);
    }

    /**
     * 查询数据库表详情
     *
     * @param tableIdentification - 数据库表主键
     * @return Result - TableBasicVO 数据库表表基础信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:07
     */
    public CommonResponse<TableVO> queryTableInfoListById(final Long tableIdentification) {
        TableVO table = new TableVO();
        // 1.数据库表表信息
        TableHeadVO tableHead = serviceByTableHeadService.queryTableListById(tableIdentification);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(tableHead, "数据库表表信息查询失败");
        table.setTableHead(tableHead);
        // 2.数据库表字段信息
        List<TableFields> tableFieldsList = serviceByTableFieldsService.list(
                Wrappers.<TableFields>lambdaQuery()
                        // 数据库表 ID
                        .eq(TableFields::getTableHeadId, tableHead.getId())
                        .orderByAsc(TableFields::getSortOrder)
        );
        if (!tableFieldsList.isEmpty()) {
            table.setTableFieldsList(TableFieldsConverter.INSTANCE.getReturnValue(tableFieldsList));
        }
        // 3.数据库表索引
        List<TableIndex> tableIndexList = serviceByTableIndexService.list(Wrappers.<TableIndex>lambdaQuery().eq(TableIndex::getTableHeadId, tableIdentification).orderByAsc(TableIndex::getCreateTime));
        if (!tableIndexList.isEmpty()) {
            table.setTableIndexList(TableIndexConverter.INSTANCE.getReturnValue(tableIndexList));
        }
        return new CommonResponse(table);
    }

    /**
     * 添加数据库表
     *
     * @param addDataBaseTable - 数据库表新增对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:07
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse addDataBaseTable(final TableAddDTO addDataBaseTable) {
        // 1.数据库表表信息
        TableHead tableHead = this.tableHeadAddVerification(addDataBaseTable.getTableHead());
        boolean saveTableHead = serviceByTableHeadService.save(tableHead);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(saveTableHead, "数据库表表添加失败");
        // 2.数据库表字段信息
        Long tableHeadId = tableHead.getId();
        ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(tableHeadId, "数据库表编号");
        List<TableFieldsAddDTO> tableFieldsAddList = addDataBaseTable.getTableFieldsList();
        ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(tableFieldsAddList, "数据库表字段信息");
        List<TableFields> tableFieldsList = TableFieldsConverter.INSTANCE.getAddEntity(tableFieldsAddList, tableHeadId);
        boolean saveTableFields = serviceByTableFieldsService.saveBatch(tableFieldsList);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(saveTableFields, "数据库表表添加失败");
        // 3.数据库表索引
        List<TableIndexAddDTO> tableIndexAddList = addDataBaseTable.getTableIndexList();
        boolean saveTableIndex = Boolean.TRUE;
        if (tableIndexAddList.size() > 0) {
            List<TableIndex> tableIndexList = TableIndexConverter.INSTANCE.addListRo2ListPo(tableIndexAddList, tableHeadId);
            saveTableIndex = serviceByTableIndexService.saveBatch(tableIndexList);
        }
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(saveTableIndex, "数据库表索引添加失败");

        return new BaseResponse();
    }

    /**
     * 复制数据库表
     *
     * @param tableIdentification - 数据库表主键
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:44
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse copyDataBaseTable(final Long tableIdentification) {
        // 1、数据库表表信息
        TableHead tableHead = serviceByTableHeadService.getById(tableIdentification);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(tableHead, "数据库表表信息复制失败，数据库表不存在");
        Integer tableHeadBackupVersion = 1;
        // 数据库-库表-备份对象
        TableHead tableHeadBackup = TableHeadConverter.INSTANCE.getDataBaseTableHeadBackup(tableHead, tableHeadBackupVersion);
        boolean saveTableHead = serviceByTableHeadService.save(tableHead);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(saveTableHead, "数据库表表复制失败");
        // 2.数据库表字段信息
        List<TableFields> tableFieldsList = serviceByTableFieldsService.queryTableFieldPermissionFilteringListByTableHeadId(tableIdentification);
        if (!tableFieldsList.isEmpty()) {
            List<TableFields> tableFieldsBackupList = TableFieldsConverter.INSTANCE.getDataBaseTableFieldsListBackup(tableFieldsList, tableHeadBackup.getId());
            boolean saveTableFields = serviceByTableFieldsService.saveBatch(tableFieldsBackupList);
            ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(saveTableFields, "数据库表字段复制失败");
        }
        // 3.数据库表索引信息
        List<TableIndex> tableIndexList = serviceByTableIndexService.list(Wrappers.<TableIndex>lambdaQuery().eq(TableIndex::getTableHeadId, tableIdentification));
        if (!tableIndexList.isEmpty()) {
            List<TableIndex> tableIndexBackupList = TableIndexConverter.INSTANCE.getDataBaseTableIndexListBackup(tableIndexList, tableHeadBackup.getId());
            boolean saveTableIndex = serviceByTableIndexService.saveBatch(tableIndexBackupList);
            ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(saveTableIndex, "数据库表索引添加失败");
        }
        return new BaseResponse();
    }

    /**
     * 修改数据库表
     *
     * @param updateDataBaseTable - 数据库表修改对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/6 11:07
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse updateDataBaseTable(final TableUpdateDTO updateDataBaseTable) {
        // 1.数据库表表信息
        TableHead tableHead = this.tableHeadUpdateVerification(updateDataBaseTable.getTableHead());
        // 2.数据库表字段信息
        List<Long> deleteFieldIds = updateDataBaseTable.getDeleteFieldIds();
        List<TableFieldsUpdateDTO> tableFieldsUpdateList = updateDataBaseTable.getTableFieldsList();
        TableFieldsDTO tableFields = this.tableFieldsUpdateVerification(tableHead, deleteFieldIds, tableFieldsUpdateList);
        // 2.1数据库表字段信息-删除
        boolean removeTableFields = serviceByTableFieldsService.removeByIds(deleteFieldIds);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(removeTableFields, "数据库表字段信息-删除失败失败");
        // 2.2数据库表字段信息-更新
        List<TableFields> tableFieldsUpdate = TableFieldsConverter.INSTANCE.getUpdateEntity(tableFields.getTableFieldsUpdateList());
        boolean updateTableFields = serviceByTableFieldsService.updateBatchById(tableFieldsUpdate);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(updateTableFields, "数据库表字段信息-更新失败");
        // 2.3数据库表字段信息-新增
        List<TableFields> tableFieldsList = tableFields.getTableFieldsList();
        boolean addTableFields = serviceByTableFieldsService.saveBatch(tableFieldsList);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(addTableFields, "数据库表字段信息-更新失败");
        tableHead = tableFields.getTableHead();
        // 3.数据库表索引信息
        List<Long> deleteIndexIds = updateDataBaseTable.getDeleteIndexIds();
        List<TableIndexUpdateDTO> tableIndexUpdateList = updateDataBaseTable.getTableIndexList();
        TableIndexDTO tableIndex = this.tableIndexUpdateVerification(tableHead, deleteIndexIds, tableIndexUpdateList);
        // 3.1数据库表索引信息-新增
        List<TableIndex> tableIndexAddList = tableIndex.getTableIndexAddList();
        boolean addTableIndex = serviceByTableIndexService.saveBatch(tableIndexAddList);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(addTableIndex, "数据库表索引信息-新增失败");
        // 3.2数据库表索引信息-更新
        List<TableIndex> tableIndexUpdate = tableIndex.getTableIndexUpdateList();
        boolean updateBatchTableIndex = serviceByTableIndexService.updateBatchById(tableIndexUpdate);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(updateBatchTableIndex, "数据库表索引信息-更新失败");
        tableHead = tableIndex.getTableHead();
        // 4.兜底控制同步状态
        if (deleteFieldIds.size() > 0 || tableFieldsUpdate.size() > 0 || tableFieldsList.size() > 0 || deleteIndexIds.size() > 0 || tableIndexAddList.size() > 0 || tableIndexUpdate.size() > 0) {
            // isSynchronize 数据库表字段删除、数据库表字段更新、数据库表字段新增、数据库表索引删除、数据库表索引新增、数据库表索引更新
            tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_N);
        }
        // 数据库表表信息-更新
        boolean updateTableHead = serviceByTableHeadService.updateById(tableHead);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(updateTableHead, "数据库表更新失败");
        return new BaseResponse();
    }

    /**
     * 数据库表同步
     *
     * @param dataBaseTableSynchronize - 数据库表同步对象
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/5 11:57
     */
    public BaseResponse doDataBaseTableSynchronize(final DataBaseTableSynchronizeDTO dataBaseTableSynchronize) {
        try {
            // 1.判断实体配置
            Long tableHeadId = dataBaseTableSynchronize.getTableHeadId();
            TableHead tableHead = serviceByTableHeadService.getById(tableHeadId);
            // 对象断言-是否非空
            ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(tableHead, "在线开发-数据库表表信息");
            String tableName = tableHead.getTableName();
            // 2.构造同步参数 TableFormConfigModel 实例
            List<TableFields> fieldList = serviceByTableFieldsService.list(new LambdaQueryWrapper<TableFields>()
                    .eq(TableFields::getTableHeadId, tableHeadId).orderByAsc(TableFields::getSortOrder));
            // 3.查询要生成数据库表的数据库连接信息
            SysDataSourceVO sysDataSource = SysDataSourceConverter.INSTANCE.getReturnValue(serviceByDataSourceService.getOne(Wrappers.<SysDataSource>lambdaQuery().eq(SysDataSource::getPoolName, DataBaseConstant.DATA_SOURCE_BUSINESS), Boolean.FALSE));
            ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(sysDataSource, "在线开发-数据库表的数据库连接信息");
            TableFormConfigModel model = TableTemplateConverter.INSTANCE.modelConvert(tableHead, sysDataSource, fieldList);
            ArgumentResponseEnum.COMMON_EXCEPTION.assertNotNullWithMsg(tableHead, "在线开发-数据库表的表单配置模型");
            // 4.依据同步类型进行不同操作
            String synchronizationMode = dataBaseTableSynchronize.getSynchronizationMode();
            if (DataBaseConstant.NORMAL_SYNCHRONIZATION.equals(synchronizationMode)) {
                // 4.1 正常同步
                this.doNormalSynchronization(tableHeadId, tableName, model);
            } else if (DataBaseConstant.FORCE_SYNCHRONIZATION.equals(synchronizationMode)) {
                // 4.2 强制同步，先删除后添加
                this.doForceSynchronization(tableName, model);
            }
            // 5.处理完表 再处理库表索引
            this.createTableIndex(tableHeadId, tableName);
            // 6.同步完成 修改同步标识
            tableHead.setIsSynchronize(CommonConstant.TO_UPPER_CASE_Y);
            serviceByTableHeadService.updateById(tableHead);
        } catch (Exception throwable) {
            ArgumentResponseEnum.COMMON_EXCEPTION.assertFail(throwable);
        }
        return new BaseResponse();
    }

    /**
     * 删除数据库表，保留信息
     *
     * @param tableIdentification - 数据库表主键
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    public BaseResponse removeDataBaseTable(final Long tableIdentification) {
        TableHead tableHead = this.tableHeadRemoveVerification(tableIdentification);
        Boolean dataBaseTableRemoveByTableName = this.doDataBaseTableRemoveByTableName(tableHead.getTableName());
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(dataBaseTableRemoveByTableName, "数据库表移除失败");
        return new BaseResponse();
    }

    /**
     * 删除数据库表所有信息
     *
     * @param tableIdentification - 数据库表主键
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse deleteDataBaseTable(final Long tableIdentification) {
        TableHead tableHead = this.tableHeadRemoveVerification(tableIdentification);
        Boolean dataBaseTableRemoveByTableName = this.doDataBaseTableRemoveByTableName(tableHead.getTableName());
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(dataBaseTableRemoveByTableName, "数据库表移除失败");
        Boolean dataBaseTableDeleteByTableIdentification = this.doDataBaseTableDeleteByTableIdentification(tableIdentification);
        ArgumentResponseEnum.COMMON_EXCEPTION.assertIsTrueWithMsg(dataBaseTableDeleteByTableIdentification, "数据库表相关删除失败");
        return new BaseResponse();
    }

}